package service

import (
	"leaf/core/conf"
	"leaf/core/log"
	. "leaf/core/tool"
	"runtime"
	"sync"
)

var wg = sync.WaitGroup{}

//var closeSig chan bool

type IService interface {
	Init(s interface{})
	Destroy()
	Run(closeSig chan bool)
	GetThreadNum() int32
}

type service struct {
	s IService
}

var slist = []*service{}

func Register(s IService) {
	ss := new(service)
	ss.s = s
	slist = append(slist, ss)
}

func Init(c chan bool) {
	for _, s := range slist {
		s.s.Init(s.s)
	}
}

func Start() {
	for i := 0; i < len(slist); i++ {
		s := slist[i]
		for j := 0; j < int(s.s.GetThreadNum()); j++ {
			wg.Add(1)
			Go(func() { run(s) })
		}
	}
}

func Destroy() {
	log.Release("destroy length of slist %v", len(slist))
	for i := len(slist) - 1; i >= 0; i-- {
		s := slist[i]
		destroy(s)
	}
	wg.Wait()
}

func run(m *service) {
	m.s.Run(GoSigChan())
	wg.Done()
}

func destroy(m *service) {
	log.Release("destroy")
	defer func() {
		if r := recover(); r != nil {
			if conf.LenStackBuf > 0 {
				buf := make([]byte, conf.LenStackBuf)
				l := runtime.Stack(buf, false)
				log.Error("%v: %s", r, buf[:l])
			} else {
				log.Error("%v", r)
			}
		}
	}()

	m.s.Destroy()
}
